# coding = utf-8
import logging
import datetime

import jwt
from django.core.cache import cache
from rest_framework.authentication import BaseAuthentication, get_authorization_header
from rest_framework import exceptions, status
from django.conf import settings
from rooms.api.utils import jwt_decode_handler, jwt_get_username_from_payload
from users.models import UserInfo

logger = logging.getLogger("django")


class JSONWebTokenVideoAuthentication(BaseAuthentication):
    """
    Token based authentication using the JSON Web Token standard.
    """
    def authenticate(self, request):
        """
        """
        token = self.get_token(request)
        # print("JSONWebTokenAuthentication::authenticate", token)
        if token is None:
            self.error_message('缺少必要的Token信息')

        try:
            payload = jwt_decode_handler(token)
            user = self.authenticate_credentials(payload)
            return (user, token)
        except jwt.ExpiredSignatureError:
            self.error_message('Token 已经过期')
        except jwt.DecodeError:
            self.error_message('Token 解码错误')
        except jwt.InvalidTokenError:
            self.error_message('无效Token 错误')

    def authenticate_credentials(self, payload):
        """
        Returns an active user that matches the payload's user id.
        """
        mode = payload.get("mode")
        user_id = None
        if mode == 0:   # 用户登录
            user_id = self.check_login_token(payload)
        elif mode == 1:     # 扫码登录
            user_id = self.check_qrcode_token(payload)
        else:
            self.error_message('非法的负载内容')

        return user_id

    def get_token(self, request):
        auth = get_authorization_header(request).split()
        logger.info("request auth:{}".format(auth))
        auth_header_prefix = settings.JWT_AUTH_HEADER_PREFIX.lower()

        if not auth:
            self.error_message('缺少Token')

        if auth[0].lower().decode() != auth_header_prefix:
            self.error_message('Authorization格式错误!')

        if len(auth) == 1:
            self.error_message('非法的 Authorization 头. 认证信息不全!')
        elif len(auth) > 2:
            self.error_message('非法的 Authorization 头. 认证信息存在多余字符')

        return auth[1]

    def check_login_token(self, payload):
        """
        :param payload:
        :return:
        """
        user_id = jwt_get_username_from_payload(payload)

        if not user_id:
            self.error_message('非法的负载内容')

        try:
            user = UserInfo.objects.get(id=user_id)

            if not user.is_active:
                self.error_message('用户账号已被禁用')

        except UserInfo.DoesNotExist:
            self.error_message('token 非法')

        return user_id

    def check_qrcode_token(self, payload):

        user_id = jwt_get_username_from_payload(payload)

        if not user_id:
            self.error_message('非法的负载内容')

        token = cache.get(user_id)
        if not token:
            self.error_message('token 非法')

        local_payload = jwt_decode_handler(token)
        if local_payload != payload:
            self.error_message('Token 非法!')

        return user_id

    def error_message(self, msg):
        msg = {
            'status_code': status.HTTP_401_UNAUTHORIZED,
            'message': msg
        }
        raise exceptions.AuthenticationFailed(msg)
